package aop.aspectj;

import java.sql.SQLException;
import java.util.concurrent.atomic.AtomicBoolean;

import org.aspectj.ajdt.internal.compiler.ast.Proceed;

import job.Job;
import job.JobContext;
import job.JobResult;
import job.JobStatus;

/**
 * 
 * @author pingwen
 */
public aspect JobAspect {

	// 全局变量
	private static boolean rejectAll = false;

	// 给类
	private AtomicBoolean Job.running = new AtomicBoolean(false);

	// pointcut jobExecuteMethod():execution(void execute(job.JobContext));
	// pointcut jobExecuteMethod():call(void Job+.execute(job.JobContext));

	pointcut jobExecuteMethod():execution(void Job+.execute(JobContext));

	pointcut jobExecute(Job j, JobContext ctx): target(j) && args(ctx) && jobExecuteMethod();

	// before(Job j, JobContext ctx):jobExecute(j,ctx){
	// System.out.println("AFTER-BEFORE:" + j.getClass().getCanonicalName()
	// + "-" + ctx.toString());
	// }

	// only return;
	// after(Job j, JobContext ctx) returning(Object ret):jobExecute(j,ctx){
	// System.out.println("AFTER-RETURN:" + j.getClass().getCanonicalName()
	// + "-" + ctx.toString());
	// }

	// only exception
	// after(Job j, JobContext ctx) throwing(SQLException e):jobExecute(j,ctx){
	// System.out.println("AFTER-THROWN:" + j.getClass().getCanonicalName()
	// + "-" + ctx.toString());
	// }

	// finally
	// after(Job j, JobContext ctx):jobExecute(j,ctx){
	// System.out.println("AFTER-FINALLY:" + j.getClass().getCanonicalName()
	// + "-" + ctx.toString());
	// }

	// proxy
	Object around(Job j, JobContext ctx) : jobExecute(j,ctx) {
		JobResult result=ctx.getResult();
		if (j.running.compareAndSet(false, true)) {
			Object ret = null;
			try {
				result.setStartTime(System.currentTimeMillis());
				result.setStatus(JobStatus.RUNNING);
				//System.out.println("AROUND:BEFORE:" + j.getClass().getCanonicalName() + "-" + ctx.toString());
				ret = proceed(j, ctx);
				result.setStatus(JobStatus.FINISHED);
				//System.out.println("AROUND:AFTER RETURN:" + j.getClass().getCanonicalName() + "-" + ctx.toString());
			} catch (Exception e) {
				//System.out.println("AROUND:AFTER THROWN:" + j.getClass().getCanonicalName() + "-" + ctx.toString());
				result.setStatus(JobStatus.THROWN);
				result.setThrowable(e);
			} finally {
				result.setEndTime(System.currentTimeMillis());
				//System.out.println("AROUND:FINALLY:" + j.getClass().getCanonicalName() + "-" + ctx.toString());
			}
			return ret;
		} else {
			result.setStatus(JobStatus.REPEATED);
			return null;
		}
	}

}
